package com.heisenhub.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.heisenhub.common.db.enums.IsDelEnum;
import com.heisenhub.common.db.service.impl.SuperServiceImpl;
import com.heisenhub.system.entity.Menu;
import com.heisenhub.system.mapper.MenuMapper;
import com.heisenhub.system.model.MenuViewVo;
import com.heisenhub.system.model.RouterMetaVo;
import com.heisenhub.system.model.VueRouter;
import com.heisenhub.system.query.MenuQuery;
import com.heisenhub.system.service.IMenuService;
import com.heisnenhub.common.module.exception.RRException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author sen
 * @since 2023-12-24
 */
@Service
public class MenuServiceImpl extends SuperServiceImpl<MenuMapper, Menu, MenuQuery> implements IMenuService {

    private final static String TOP_NODE_ID = "0";

    @Override
    public List<Menu> listAll() {
        return this.list();
    }

    /**
     *  查找user 权限
     * @param username
     * @return
     */
    @Override
    public List<Menu> findUserPermissions(String username) {
        return this.baseMapper.findUserPermissions(username);
    }

    @Override
    public List<VueRouter<Menu>> getUserRouters(String username) {
        if(StringUtils.isEmpty(username)) throw new RRException("username 为空");
        List<VueRouter<Menu>> routes = new ArrayList<>();
        List<Menu> menus = this.baseMapper.findUserMenus(username);

        for (Menu menu : menus) {
            VueRouter<Menu> route = new VueRouter<>();
            route.setId(String.valueOf(menu.getId()));
            route.setParentId(String.valueOf(menu.getParentId()));
            route.setPath(menu.getPath());
            route.setComponent(menu.getComponent());
            route.setName(menu.getMenuName());
            route.setMeta(new RouterMetaVo(menu.getMenuName(), menu.getIcon()));
            routes.add(route);
        }

        return buildVueRouter(routes);
    }

    /**
     *
     * @param type type不为空 and type=1 时 只查询菜单
     * @return
     */
    @Override
    public List<MenuViewVo> findTreeAllMetaView(Integer type) {
        List<MenuViewVo> treeMenus = new ArrayList<>();

        QueryWrapper<Menu> wq = new QueryWrapper<>();
        wq.eq(Menu.DEL, IsDelEnum.NORMAL);
        if(1==type)   wq.eq(Menu.TYPE, "1");
        List<Menu> menus = this.baseMapper.selectList(wq);

        ArrayList<MenuViewVo> sysMenuViewVos = new ArrayList<>();

        for (Menu menu : menus) {
            MenuViewVo menuVo = new MenuViewVo();
            BeanUtils.copyProperties(menu,menuVo);
            sysMenuViewVos.add(menuVo);
        }


        for (MenuViewVo menu : sysMenuViewVos) {
            Long parentId = menu.getParentId();
            if (parentId == null || TOP_NODE_ID.equals(parentId.toString()) ) {
                treeMenus.add(menu);
                continue;
            }

            for (MenuViewVo prentMenu : sysMenuViewVos) {
                Long id = prentMenu.getMenuId();

                if (id != null && id.equals(parentId)) {
                    if (CollectionUtils.isEmpty(prentMenu.getChildren()))
                        prentMenu.initChildren();

                    prentMenu.getChildren().add(menu);

                }
            }
        }


        return treeMenus;
    }

    /**
     *  查询树状菜单
     * @return
     */
    @Override
    public List<MenuViewVo> findTreeByMenusaView() {
        return  findTreeAllMetaView(1);
    }

    public static <T> List<VueRouter<T>> buildVueRouter(List<VueRouter<T>> routes) {
        if (routes == null) {
            return null;
        }
        List<VueRouter<T>> topRoutes = new ArrayList<>();
        VueRouter<T> router = new VueRouter<>();
        for (VueRouter<T> route : routes) {
            String parentId = route.getParentId();
            if (parentId == null || parentId.equals(TOP_NODE_ID)) {
                topRoutes.add(route);
                continue;
            }
            for (VueRouter<T> parent : routes) {
                String id = parent.getId();
                if (id != null && id.equals(parentId)) {
                    if (parent.getChildren() == null)
                        parent.initChildren();
                    parent.getChildren().add(route);
                    parent.setAlwaysShow(true);
                    parent.setHasChildren(true);
                    route.setHasParent(true);
                    parent.setHasParent(true);
                }
            }
        }

        return topRoutes;
    }
}
